#ifndef __SHM_HPP__
#define __SHM_HPP__
#include <cstdio>
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/types.h>

std::string gpathname = ".";
int gproj_id = 0x66;
int gdefaultsize = 4096; // 共享内存的大小，4kb的整数倍，4KB对齐(内核层面)

class ShareMemory
{
private:
    bool CreateHelper(int flags)
    {
        _key = ftok(gpathname.c_str(), gproj_id);
        if (_key < 0)
        {
            perror("ftok");
            return false;
        }
        printf("形成键值成功: 0x%x\n", _key);

        _shmid = shmget(_key, _size, flags); // 创建全新的shm
        if (_shmid < 0)
        {
            perror("shmget");
            return false;
        }
        printf("shmid: %d\n", _shmid);
        return true;
    }

public:
    ShareMemory(int size=gdefaultsize)
    :_size(size), _key(0), _shmid(-1),
    _start_addr(nullptr),_windex(0),_rindex(0),
    _datastart(nullptr),
    _num(nullptr)
    {}
    bool Creat()
    {
        return CreateHelper(IPC_CREAT|IPC_EXCL|0x666);
    }
    bool Get()
    {
        return CreateHelper(IPC_CREAT);
    }
    bool Attach()
    {
        _start_addr=shmat(_shmid,nullptr,0);
        if((long long)_start_addr==-1)
        {
            perror("shmat");
            return false;
        }

        _num=(int*)_start_addr;
        _datastart=(char*)_datastart+sizeof(int);
        return true;
    }
    void SetZero()
    {
        *_num = 0;
    }
    bool Dttch()
    {
        int n=shmdt(_start_addr);
        if(n==-1)
        {
            perror("shmdt");
            return false;
        }
        return true;

    }
    void AddChar(char ch)
    {
        if(*_num==_size)
        {
            return ;
        }
        ((char*)_datastart)[_windex++]=ch;
        ((char*)_datastart)[_windex]='\0';
        _windex %= _size;
        (*_num)++;
    }
    void PopChar(char *ch)
    {
        if(_num==0)
        {return;}
        *ch=((char*)_datastart)[_rindex++];
          _rindex %= _size;
        (*_num)--;
        printf("%s\n", _datastart);
    }
     bool RemoveShm()
    {
        int n = shmctl(_shmid, IPC_RMID, nullptr);
        if (n < 0)
        {
            perror("shmctl");
            return false;
        }

        std::cout << "删除shm成功" << std::endl;
        return true;
    }
     void PrintAttr()
    {
        struct shmid_ds ds;
        int n = shmctl(_shmid, IPC_STAT, &ds);
        if(n < 0)
        {
            perror("shmctl");
            return;
        }

        // 打印输出shm相关属性
        printf("key: 0x%x\n", ds.shm_perm.__key);
        printf("size: %ld\n", ds.shm_segsz);
        printf("atime: %lu\n", ds.shm_atime);
        printf("nattach: %ld\n", ds.shm_nattch);
    }
    ~ShareMemory() {}
private:
    key_t _key;
    int _size;
    int _shmid;
    void *_start_addr;
    int *_num;
    char *_datastart;
    int _windex;
    int _rindex;
};

#endif 
